from Quaternion import Quat
from numpy import *
from numpy.linalg import norm


def project_click(x, y):
    l = sqrt(x*x + y*y)
    if l > 1:
        return r_[x/l, y/l, 0]
    else:
        return r_[x, y, -sqrt(1 - l*l)]
    

class Trackball:
    def __init__(self):
        self.a = None
        self.mtx = eye(3)
        self.prev_mtx = None
        self.mouse = False
        
    def mouse_click(self, x, y):
        self.a = project_click(x, y)
        self.prev_mtx = self.mtx
        self.mouse = True
    
    def mouse_move(self, x, y):
        if not self.mouse:
            return
    
        b = project_click(x, y)
        
        if norm(self.a - b) < 0.0001:
            return
        
        axis = cross(self.a, b)
        axis /= norm(axis)
        angle = arccos(dot(self.a, b))
        q = Quat(r_[axis * sin(angle / 2), cos(angle / 2)])
        self.mtx = matrix(q.transform) * self.prev_mtx
        
    def mouse_release(self):
        self.mouse = False

    def get_matrix(self):
        return self.mtx

